﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include  "ActionCreateGridGroupNew.h"

#include "GbmpModelViewUtil.h"
#include "Vector2dUtils.h"
#include "Vector3dUtils.h"
#include "ILine3d.h"
#include "IArc3d.h"
#include "ICurve3d.h"
#include "IPlane.h"
#include "IUiView.h"
#include "IPickPointAction.h"
#include "IUserTransaction.h"
#include "IUiDocument.h"
#include "ITemporaryDimensionContext.h"
#include "ITemporaryDimensionManager.h"
#include "IElementBasicInformation.h"
#include "IDocument.h"
#include "IGraphicsLine.h"
#include "IModelView.h"
#include "ISnap.h"
#include "IGridNew.h"
#include "GridNewInput.h"
#include "AlgorithmProject.h"
#include "ICommandManager.h"
#include "IGraphicsElementShape.h"
#include "GridNewUtils.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

//DEFAULT_GRID_GROUP_LINE_OUT_EXTENTS_LENGTH=4000, 批量轴网 默认外向延长长度，单位：mm
const double DEFAULT_GRID_GROUP_LINE_OUT_EXTENTS_LENGTH = 4000.0f;
//DEFAULT_GRID_GROUP_LINE_OUT_EXTENTS_ANGLE=pi/6, 辐射批量轴网 默认外向延长角度，单位：弧度
const double DEFAULT_GRID_GROUP_LINE_OUT_EXTENTS_ANGLE = Constants::MATH_PI_6;

///////////////////////////////////////////
ActionCreateGridGroupNewBase::ActionCreateGridGroupNewBase()
{
    m_isUserCancelled = false;
    m_bRotate = false;
    m_drawGridGroupStatus = IDS_Not_Started;
}

void ActionCreateGridGroupNewBase::InitAction(gcmp::IUiView* pCurrentView)
{
    GettingGridGroupPlacePoint();
}

void ActionCreateGridGroupNewBase::OnChildActionFinished(gcmp::IUiView* pCurrentView, const gcmp::ActionOutput& childActionReturnParam)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCurrentView, L"pCurrentView为空",L"GDMPLab",L"2024-03-30");
    if (m_isUserCancelled)
    {
        // 如果用户选择退出
        CleanupTempGraphicsShape();
        UpdateView();

        //起新cmd时ActionMgr默认把Action栈清空
        ICommandManager *pCmdMgr = ICommandManager::Get();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pCmdMgr, L"pCmdMgr为空",L"GDMPLab",L"2024-03-30");
        pCmdMgr->SendCommand(this->GetCommandId());

        return;
    }

    IUiDocument* pUiDoc = pCurrentView->GetUiDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDoc, L"pUiDoc指针无效",L"GDMPLab",L"2024-03-30");
    IDocument *pDoc = pUiDoc->GetDbDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc指针无效",L"GDMPLab",L"2024-03-30");
    IModelView *pModelView = pCurrentView->GetModelView();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView, L"pModelView指针无效",L"GDMPLab",L"2024-03-30");

    if (m_bRotate)
    {
        if (IDS_Getting_PlacePoint == m_drawGridGroupStatus)
        {
            GettingGridGroupDirectionPoint();
        }
        else if (IDS_Getting_DirectionPoint == m_drawGridGroupStatus)
        {
            double rotateAngle = GetRotateAngleOnWorkPlane(m_placePt, m_directionPt, pModelView);
            OwnerPtr<IUserTransaction> ut = IUserTransaction::Create(pDoc, GBMP_TR(L"批量创建轴网"));
            std::vector<IGridNew*> gridGroup = CreateGridGroup(pDoc, pModelView, m_placePt, rotateAngle, ElementCreationOptions::Normal);
            ut->Commit();
            UpdateView();
            MarkFinishStatus(ActionFinishStatus::Successful);
        }
    }
    else
    {
        OwnerPtr<IUserTransaction> ut = IUserTransaction::Create(pDoc, GBMP_TR(L"批量创建轴网"));
        std::vector<IGridNew*> gridGroup = CreateGridGroup(pDoc, pModelView, m_placePt, 0, ElementCreationOptions::Normal);
        ut->Commit();
        UpdateView();
        MarkFinishStatus(ActionFinishStatus::Successful);
    }
}

std::wstring ActionCreateGridGroupNewBase::GetPromptMessage() const
{
    switch (m_drawGridGroupStatus)
    {
    case EnDrawGridGroupStatus::IDS_Getting_PlacePoint:
        return GBMP_TR(L"批量绘制轴网 - 请输入放置点");
    case EnDrawGridGroupStatus::IDS_Getting_DirectionPoint:
        return GBMP_TR(L"批量绘制轴网 - 请输入旋转结束线");
    default:
        return L"";
    }
}

void ActionCreateGridGroupNewBase::GettingGridGroupPlacePoint()
{
    m_drawGridGroupStatus = IDS_Getting_PlacePoint;
    SetPromptMessage(GetPromptMessage());
    m_isUserCancelled = false;

    gcmp::OwnerPtr<IPickPointAction> upPickPointAction(IPickPointAction::Create(
        PickPointExchangeData(&m_placePt, &m_isUserCancelled, &m_pickedPoints)
        , IPickPointAction::CreateMoveCallback(&ActionCreateGridGroupNewBase::PreviewByPlacePoint, this)));
    StartChildAction(TransferOwnership(upPickPointAction));
}

void ActionCreateGridGroupNewBase::GettingGridGroupDirectionPoint()
{
    m_drawGridGroupStatus = IDS_Getting_DirectionPoint;
    SetPromptMessage(GetPromptMessage());
    m_isUserCancelled = false;
    m_pickedPoints.push_back(m_placePt + Vector3d::UnitX);
    gcmp::OwnerPtr<IPickPointAction> upPickPointAction(IPickPointAction::Create(
        PickPointExchangeData(&m_directionPt, &m_isUserCancelled, &m_pickedPoints)
        , IPickPointAction::CreateMoveCallback(&ActionCreateGridGroupNewBase::PreviewByPlacePointWithDirection, this)));
    upPickPointAction->SetFirstPoint(m_placePt);
    StartChildAction(TransferOwnership(upPickPointAction));
}

void ActionCreateGridGroupNewBase::PreviewByPlacePoint(IUiView* pCurrentView, const Vector3d& pos, const Vector3d& mousePt)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCurrentView, L"pCurrentView指针无效",L"GDMPLab",L"2024-03-30");
    IModelView *pModelView = pCurrentView->GetModelView();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView, L"pModelView指针无效",L"GDMPLab",L"2024-03-30");
    IDocument *pDoc = pModelView->GetDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc指针无效",L"GDMPLab",L"2024-03-30");

    std::vector<IGridNew*> gridGroup = CreateGridGroup(pDoc, pModelView, pos, 0, ElementCreationOptions::Transient);
    OwnerPtr<IGraphicsNodeGroup> opGridGroupGrep = GetGridGroupGrep(gridGroup, pModelView);
    DeleteGridGroup(pDoc, gridGroup);
    if (!opGridGroupGrep)
        return;
    DrawTempGraphicsNodeGroup(TransferOwnership(opGridGroupGrep));
}

void ActionCreateGridGroupNewBase::PreviewByPlacePointWithDirection(IUiView* pCurrentView, const Vector3d& pos, const Vector3d& mousePt)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCurrentView, L"pCurrentView指针无效",L"GDMPLab",L"2024-03-30");
    IModelView *pModelView = pCurrentView->GetModelView();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView, L"pModelView指针无效",L"GDMPLab",L"2024-03-30");
    IDocument *pDoc = pModelView->GetDocument();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc指针无效",L"GDMPLab",L"2024-03-30");

    double rotateAngle = GetRotateAngleOnWorkPlane(m_placePt, pos, pModelView);

    std::vector<IGridNew*> gridGroup = CreateGridGroup(pDoc, pModelView, m_placePt, rotateAngle, ElementCreationOptions::Transient);
    OwnerPtr<IGraphicsNodeGroup> opGridGroupGrep = GetGridGroupGrep(gridGroup, pModelView);
    DeleteGridGroup(pDoc, gridGroup);
    if (!opGridGroupGrep)
        return;

    // 临时尺寸标注
    opGridGroupGrep->AddChild(IGraphicsLine::Create(m_placePt, pos));
    Vector3d angleStartPt = m_placePt + Vector3d::UnitX * 1000;
    OwnerPtr<ITemporaryDimensionContext> opCtx = ITemporaryDimensionContext::CreateRotationContext(
        m_placePt, angleStartPt, pos, GbmpModelViewUtil::GetWorkPlaneCoordinate(pModelView));
    opGridGroupGrep->AddChild((ITemporaryDimensionManager::Get()->GenerateTemporaryDimensionGraphics(opCtx.get())));

    DrawTempGraphicsNodeGroup(TransferOwnership(opGridGroupGrep));
}

double ActionCreateGridGroupNewBase::GetRotateAngleOnWorkPlane(const Vector3d &start, const Vector3d &end, const IModelView* pModelView) const
{
    Vector3d dir = end - start;
    dir.Normalize();
    Coordinate3d coord = GbmpModelViewUtil::GetWorkPlaneCoordinate(pModelView);
    return Vector2dUtils::GetAngle(Vector2d(coord.GetX().GetX(), coord.GetX().GetY()), Vector2d(dir.X(), dir.Y()));
}

OwnerPtr<IGraphicsNodeGroup> ActionCreateGridGroupNewBase::GetGridGroupGrep(const std::vector<IGridNew*> &gridGroup, const IModelView* pModelView) const
{
    if (gridGroup.empty())
    {
        return nullptr;
    }
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelView, L"pModelView指针无效",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IPlane> opWorkPlane = pModelView->GetWorkPlane();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opWorkPlane, L"opWorkPlane指针无效",L"GDMPLab",L"2024-03-30");

    double viewScale = pModelView->GetViewScale();
    OwnerPtr<IGraphicsNodeGroup> opGridGroupGrep = IGraphicsNodeGroup::Create();
    FOR_EACH(pGrid, gridGroup)
    {
        if (opGridGroupGrep&&pGrid)
        {
            OwnerPtr<IGraphicsElementShape> opGridShape = pGrid->CreateElementShapeBasedOnPlane(opWorkPlane.get(), viewScale,pModelView);
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opGridShape, L"opGridShape指针无效",L"GDMPLab",L"2024-03-30");
            opGridGroupGrep->AddChild(TransferOwnership(opGridShape));
        }
    }
    return TransferOwnership(opGridGroupGrep);
}

gcmp::IGridNew* gcmp::ActionCreateGridGroupNewBase::CreateGridByCurveAndSetProperty(IDocument* pDoc, const IModelView* pModelView, const ICurve3d* pCurve, const std::wstring& name, ElementCreationOptions eco /*= ElementCreationOptions::Normal */, bool startTagVisible/*=true*/, bool endTagVisible/*=true*/)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pCurve, L"pCurve为空",L"GDMPLab",L"2024-03-30");
    GridNewInput gridNewInput;
    gridNewInput.Document = pDoc;
    gridNewInput.GridNewName = name;
    gridNewInput.CreationOption = eco;

    // 当前视图的工作平面高度
    OwnerPtr<IPlane> opWorkPlane = pModelView->GetWorkPlane();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opWorkPlane, L"opWorkPlane为空",L"GDMPLab",L"2024-03-30");
    gridNewInput.verticalExtents = GridNewUtils::GetGridDefaultVerticalExtents(pDoc, opWorkPlane.get(), eco);
    GridNewUtils::setGridNewPresetParameter(pDoc,gridNewInput.StartTagVisble, gridNewInput.EndTagVisble);
    OwnerPtr<ICurve2d> opCurve = AlgorithmProject::Project(pCurve, opWorkPlane.get());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opCurve, L"opCurve为空",L"GDMPLab",L"2024-03-30");
    gridNewInput.VecOpCurve.push_back(TransferOwnership(opCurve));
    IGridNew* pGrid =IGridNew::Create(gridNewInput);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGrid, L"pGrid为空",L"GDMPLab",L"2024-03-30");

    //设置名字、轴号可见性(默认末端可见)
    IElement* pOwnerElement = pGrid->GetOwnerElement();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pOwnerElement, L"pOwnerElement为空",L"GDMPLab",L"2024-03-30");
    IElementBasicInformation* pElementBaicInfo = pOwnerElement->GetBasicInformation();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElementBaicInfo, L"pElementBaicInfo为空",L"GDMPLab",L"2024-03-30");
    pElementBaicInfo->SetName(name);

    pGrid->SetStartTagVisibleInPlanView(startTagVisible);
    pGrid->SetEndTagVisibleInPlanView(endTagVisible);


    return pGrid;
}

bool ActionCreateGridGroupNewBase::DeleteGridGroup(IDocument *pDoc, std::vector<IGridNew*> vecGrids)
{
    bool bDeleteAll = true;
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    FOR_EACH(pGrid, vecGrids)
    {
        if (pGrid)
        {
            IElement* ownerElement = pGrid->GetOwnerElement();
            DBG_WARN_AND_RETURN_FALSE_UNLESS(ownerElement, L"ownerElement为空",L"GDMPLab",L"2024-03-30");
            ElementId elementId = ownerElement->GetElementId();
            bDeleteAll = pDoc->DeleteElement(elementId) && bDeleteAll;
        }
    }
    return bDeleteAll;
}

///////////////////////////////////////////
gcmp::ActionCreateOrthogonalGridGroupNew::ActionCreateOrthogonalGridGroupNew(const OrthogonalGridGroupParam &param):m_param(param)
{
    SetRotatable(m_param.Rotate);
}

std::vector<IGridNew*> ActionCreateOrthogonalGridGroupNew::CreateGridGroup(IDocument* pDoc, const IModelView* pModelView, const Vector3d& anchorPt, double rotateAngle/*=0*/, ElementCreationOptions eco /*= ElementCreationOptions::Normal */)
{
    std::vector<IGridNew*> vecGrids;
    DBG_WARN_AND_RETURN_UNLESS(pDoc, vecGrids, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_UNLESS(pModelView, vecGrids, L"pModelView为空",L"GDMPLab",L"2024-03-30");

    const OrthogonalGridGroupParam::AxisPositionSet &vecHorizAxis = m_param.HorizAxis;
    const OrthogonalGridGroupParam::AxisPositionSet &vecVertiAxis = m_param.VertiAxis;
    DBG_WARN_AND_RETURN_UNLESS(vecHorizAxis.size() > 1 && vecVertiAxis.size() > 1, vecGrids, L"轴间距不合法",L"GDMPLab",L"2024-03-30");

    //横向、纵向方向 的 首尾轴线 间距值
    double horizonTotalGap = vecVertiAxis.rbegin()->second;
    double verticalTotalGap = vecHorizAxis.rbegin()->second;
    // 锚点 分别指向 横向轴线起点、横向轴线终点、纵向轴线起点、纵向轴线终点 的单位向量
    Vector3d anchorToStartDir = Vector3dUtils::RotateVectorAroundAxis(Vector3d::NegaUnitX, Vector3d::UnitZ, rotateAngle);
    Vector3d anchorToEndtDir = -anchorToStartDir;
    Vector3d anchorToTopDir = Vector3dUtils::RotateVectorAroundAxis(Vector3d::UnitX, Vector3d::UnitZ, rotateAngle + Constants::MATH_PI_2);
    Vector3d anchorToBottomDir = -anchorToTopDir;
    //轴网默认外向延长长度
    double lineOutExtent = DEFAULT_GRID_GROUP_LINE_OUT_EXTENTS_LENGTH;

    //按锚点类型生成横向、纵向首根轴线的起终点（轴线画法：从下到上，从左到右）
    Vector3d horizonFirstLineStartPoint;
    Vector3d horizonFirstLineEndPoint;
    Vector3d verticalFirstLineStartPoint;
    Vector3d verticalFirstLineEndPoint;

    switch (m_param.AnchorType)
    {
    case EnOrthogonalGridGroupAnchorPositionType::Center:
    {
        horizonFirstLineStartPoint = anchorPt + anchorToStartDir*(lineOutExtent + horizonTotalGap / 2) + anchorToBottomDir*verticalTotalGap / 2;
        horizonFirstLineEndPoint = anchorPt + anchorToEndtDir*(lineOutExtent + horizonTotalGap / 2) + anchorToBottomDir*verticalTotalGap / 2;
        verticalFirstLineStartPoint = anchorPt + anchorToTopDir*(lineOutExtent + verticalTotalGap / 2) + anchorToStartDir*horizonTotalGap / 2;
        verticalFirstLineEndPoint = anchorPt + anchorToBottomDir*(lineOutExtent + verticalTotalGap / 2) + anchorToStartDir*horizonTotalGap / 2;
        break;
    }
    case EnOrthogonalGridGroupAnchorPositionType::TopLeft:
    {
        horizonFirstLineStartPoint = anchorPt + anchorToStartDir*lineOutExtent + anchorToBottomDir*verticalTotalGap;
        horizonFirstLineEndPoint = anchorPt + anchorToEndtDir*(lineOutExtent + horizonTotalGap) + anchorToBottomDir*verticalTotalGap;
        verticalFirstLineStartPoint = anchorPt + anchorToTopDir*lineOutExtent;
        verticalFirstLineEndPoint = anchorPt + anchorToBottomDir*(lineOutExtent + verticalTotalGap);
        break;
    }
    case EnOrthogonalGridGroupAnchorPositionType::TopRight:
    {
        horizonFirstLineStartPoint = anchorPt + anchorToStartDir*(lineOutExtent + horizonTotalGap) + anchorToBottomDir*verticalTotalGap;
        horizonFirstLineEndPoint = anchorPt + anchorToEndtDir*lineOutExtent + anchorToBottomDir*verticalTotalGap;
        verticalFirstLineStartPoint = anchorPt + anchorToTopDir*lineOutExtent + anchorToStartDir*horizonTotalGap;
        verticalFirstLineEndPoint = anchorPt + anchorToBottomDir*(lineOutExtent + verticalTotalGap) + anchorToStartDir*horizonTotalGap;
        break;
    }
    case EnOrthogonalGridGroupAnchorPositionType::BottomLeft:
    {
        horizonFirstLineStartPoint = anchorPt + anchorToStartDir*lineOutExtent;
        horizonFirstLineEndPoint = anchorPt + anchorToEndtDir*(lineOutExtent + horizonTotalGap);
        verticalFirstLineStartPoint = anchorPt + anchorToTopDir*(lineOutExtent + verticalTotalGap);
        verticalFirstLineEndPoint = anchorPt + anchorToBottomDir*lineOutExtent;
        break;
    }
    case EnOrthogonalGridGroupAnchorPositionType::BottomRight:
    {
        horizonFirstLineStartPoint = anchorPt + anchorToStartDir*(lineOutExtent + horizonTotalGap);
        horizonFirstLineEndPoint = anchorPt + anchorToEndtDir*lineOutExtent;
        verticalFirstLineStartPoint = anchorPt + anchorToTopDir*(lineOutExtent + verticalTotalGap) + anchorToStartDir*horizonTotalGap;
        verticalFirstLineEndPoint = anchorPt + anchorToBottomDir*lineOutExtent + anchorToStartDir*horizonTotalGap;
        break;
    }
    default:
        DBG_WARN_AND_RETURN_UNLESS(false, vecGrids, L"锚点类型不合法",L"GDMPLab",L"2024-03-30");
    }

    //批量生成轴线
    Vector3d currentGridLineStartPoint;
    Vector3d currentGridLineEndPoint;
    FOR_EACH(horizAxis, vecHorizAxis)
    {
        currentGridLineStartPoint = horizonFirstLineStartPoint + anchorToTopDir*horizAxis.second;
        currentGridLineEndPoint = horizonFirstLineEndPoint + anchorToTopDir*horizAxis.second;

        OwnerPtr<ILine3d> opLine = ILine3d::Create(currentGridLineStartPoint, currentGridLineEndPoint);
        IGridNew* pGridTmp = CreateGridByCurveAndSetProperty(pDoc, pModelView, opLine.get(), horizAxis.first, eco);
        if (pGridTmp)
        {
            vecGrids.push_back(pGridTmp);
        }
    }
    FOR_EACH(verticalAxis, vecVertiAxis)
    {
        currentGridLineStartPoint = verticalFirstLineStartPoint + anchorToEndtDir*verticalAxis.second;
        currentGridLineEndPoint = verticalFirstLineEndPoint + anchorToEndtDir*verticalAxis.second;

        OwnerPtr<ILine3d> opLine = ILine3d::Create(currentGridLineStartPoint, currentGridLineEndPoint);
        IGridNew* pGridTmp = CreateGridByCurveAndSetProperty(pDoc, pModelView, opLine.get(), verticalAxis.first, eco);
        if (pGridTmp)
        {
            vecGrids.push_back(pGridTmp);
        }
    }

    return vecGrids;
}

///////////////////////////////////////////
gcmp::ActionCreateRadialGridGroupNew::ActionCreateRadialGridGroupNew(const RadialGridGroupParam& param):m_param(param)
{
    SetRotatable(m_param.Rotate);
}

std::vector<IGridNew*> gcmp::ActionCreateRadialGridGroupNew::CreateGridGroup(IDocument* pDoc, const IModelView* pModelView, const Vector3d& anchorPt, double rotateAngle /*= 0*/, ElementCreationOptions eco /*= ElementCreationOptions::Normal*/)
{
    std::vector<IGridNew*> vecGrids;
    DBG_WARN_AND_RETURN_UNLESS(pDoc, vecGrids, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_UNLESS(pModelView, vecGrids, L"pModelView为空",L"GDMPLab",L"2024-03-30");

    const OrthogonalGridGroupParam::AxisPositionSet &vecRadiusAxis = m_param.RadiusAxis;
    const OrthogonalGridGroupParam::AxisPositionSet &vecCircularAxis = m_param.CircularAxis;
    DBG_WARN_AND_RETURN_UNLESS(vecRadiusAxis.size() > 1 && vecCircularAxis.size() > 1, vecGrids, L"轴间距(角)不合法",L"GDMPLab",L"2024-03-30");

    //圆心到最外层圆弧距离、起终径向轴线的夹角值
    double radiusTotalLength = (*vecCircularAxis.rbegin()).second;
    double circularTotalAngle = (*vecRadiusAxis.rbegin()).second;
    radiusTotalLength += m_param.InnerRadius;
    circularTotalAngle = MathUtils::AngleToRadians(circularTotalAngle);

    //轴网默认外向延长长度、角度
    double lineOutExtentLength = DEFAULT_GRID_GROUP_LINE_OUT_EXTENTS_LENGTH;
    double lineOutExtentAngle = DEFAULT_GRID_GROUP_LINE_OUT_EXTENTS_ANGLE;

    // 鼠标点指向锚点、锚点指向鼠标点 的单位向量
    Vector3d mouseToAnchorDir = Vector3dUtils::RotateVectorAroundAxis(Vector3d::NegaUnitX, Vector3d::UnitZ, rotateAngle);
    Vector3d anchorToMouseDir = -mouseToAnchorDir;

    //按锚点类型生成 首根径向轴线的起、终点（轴线画法：径向轴线逆时针，从圆心起点向外）、首根径向轴线(向外)单位向量
    Vector3d radiusFirstLineStartPoint;
    Vector3d radiusFirstLineEndPoint;
    Vector3d radiusFirstLineDir;

    switch (m_param.AnchorType)
    {
    case EnRadialGridGroupAnchorPositionType::Center:
    {
        radiusFirstLineDir = anchorToMouseDir;
        radiusFirstLineStartPoint = anchorPt;
        break;
    }
    case EnRadialGridGroupAnchorPositionType::Left:
    {
        radiusFirstLineDir = Vector3dUtils::RotateVectorAroundAxis(anchorToMouseDir, Vector3d::UnitZ, -circularTotalAngle);
        radiusFirstLineStartPoint = anchorPt + mouseToAnchorDir*radiusTotalLength;
        break;
    }
    case EnRadialGridGroupAnchorPositionType::Right:
    {
        radiusFirstLineDir = anchorToMouseDir;
        radiusFirstLineStartPoint = anchorPt + mouseToAnchorDir*radiusTotalLength;
        break;
    }
    default:
        DBG_WARN_AND_RETURN_UNLESS(false, vecGrids, L"锚点类型不合法",L"GDMPLab",L"2024-03-30");
    }
    radiusFirstLineEndPoint = radiusFirstLineStartPoint + radiusFirstLineDir*(radiusTotalLength + lineOutExtentLength);

    //生成 圆心（即首根径向轴线起点）指向环向轴线（环向轴线画法：环向轴线从内到外，顺时针）终点的单位向量
    Vector3d centerToCircularEndtDir;
    centerToCircularEndtDir = Vector3dUtils::RotateVectorAroundAxis(radiusFirstLineDir, Vector3d::UnitZ, -lineOutExtentAngle);

    //生成首根环向轴线的终点
    //tmpPoint：第一根径向轴线上，距离圆心为内弧半径长度的点
    Vector3d CircularFirstLineEndPoint;
    Vector3d tmpPoint = radiusFirstLineStartPoint + radiusFirstLineDir*m_param.InnerRadius;
    CircularFirstLineEndPoint = Vector3dUtils::RotatePointAroundAxis(tmpPoint, radiusFirstLineStartPoint, Vector3d::UnitZ, -lineOutExtentAngle);

    //批量生成轴线
    Vector3d currentGridLineStartPoint;
    Vector3d currentGridLineEndPoint;
    FOR_EACH(circularAxis, vecCircularAxis)
    {
        currentGridLineEndPoint = CircularFirstLineEndPoint + centerToCircularEndtDir*circularAxis.second;
        currentGridLineStartPoint = Vector3dUtils::RotatePointAroundAxis(currentGridLineEndPoint, radiusFirstLineStartPoint, Vector3d::UnitZ, circularTotalAngle + 2 * lineOutExtentAngle);
        //currentGridLineMidPoint: start->end顺时针圆弧上任一点即可，不是实际的中点
        Vector3d currentGridLineMidPoint = Vector3dUtils::RotatePointAroundAxis(currentGridLineEndPoint, radiusFirstLineStartPoint, Vector3d::UnitZ, circularTotalAngle / 2);

        OwnerPtr<IArc3d> opArc = IArc3d::Create(currentGridLineStartPoint, currentGridLineEndPoint, currentGridLineMidPoint);
        IGridNew* pGridTmp = CreateGridByCurveAndSetProperty(pDoc, pModelView, opArc.get(), circularAxis.first, eco);
        if (pGridTmp)
        {
            vecGrids.push_back(pGridTmp);
        }
    }
    FOR_EACH(radiusAxis, vecRadiusAxis)
    {
        currentGridLineStartPoint = radiusFirstLineStartPoint;
        currentGridLineEndPoint = Vector3dUtils::RotatePointAroundAxis(radiusFirstLineEndPoint, radiusFirstLineStartPoint, Vector3d::UnitZ, MathUtils::AngleToRadians(radiusAxis.second));
        
        OwnerPtr<ILine3d> opLine = ILine3d::Create(currentGridLineStartPoint, currentGridLineEndPoint);
        IGridNew* pGridTmp = CreateGridByCurveAndSetProperty(pDoc, pModelView, opLine.get(), radiusAxis.first, eco);
        if (pGridTmp)
        {
            vecGrids.push_back(pGridTmp);
        }
    }


    return vecGrids;
}

